
package com.insigma.business.qrcode.common._provider.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import com.insigma.business.qrcode.common.converter.CommonAdminAreaProviderConverter;
import com.insigma.business.qrcode.common.dao.CommonAdminAreaDO;
import com.insigma.business.qrcode.common.dto.CommonAdminAreaBSearcher;
import com.insigma.business.qrcode.common.dto.CommonAdminAreaDTO;
import com.insigma.business.qrcode.common.dto.CommonAdminAreaSearchRequest;
import com.insigma.business.qrcode.common._provider.CommonAdminAreaProvider;
import com.insigma.business.qrcode.common.service.CommonAdminAreaService;
import com.insigma.business.qrcode.common.template.BasePagingResponse;
import com.insigma.business.qrcode.common.template.area.BaseProviderImpl;
import com.insigma.business.qrcode.common.template.area.ScenarioCodeEnum;
import com.insigma.business.qrcode.common.template.area.ServiceCallback;
import com.insigma.business.qrcode.common.util.AdminAreaCodeUtils;
import com.insigma.business.qrcode.common.util.ResponseUtils;
import com.insigma.business.qrcode.common.vo.BaseDeleteRequest;
import com.insigma.business.qrcode.common.vo.BaseResponse;
import com.insigma.business.qrcode.soldier.dao.SoldierBasicInfoDao;
import com.insigma.business.qrcode.soldier.dto.SoldierBasicInfoDTO;
import com.insigma.business.qrcode.soldier.entity.AreaCodeEntity;
import com.insigma.business.qrcode.soldier.entity.SoldierBasicInfoDO;
import com.insigma.business.qrcode.soldier.request.BaseGetRequest;
import com.insigma.business.qrcode.soldier.service.SoldierBasicInfoService;
import com.insigma.business.qrcode.soldier.util.BizCheckUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
@Component("commonAdminAreaProvider")
public class CommonAdminAreaProviderImpl extends BaseProviderImpl implements CommonAdminAreaProvider {

    @Autowired
    private CommonAdminAreaService commonAdminAreaService;


    @Autowired(required = false)
    private SoldierBasicInfoDao soldierBasicInfoDao;

    @Autowired
    private SoldierBasicInfoService soldierBasicInfoService;

    Map<String, AreaCodeEntity> hzShiMap;


    @Override
    public BaseResponse<CommonAdminAreaDTO> findAdminAreaOfEmployee(String userId) {
        CommonAdminAreaDO adminAreaOfEmployee = commonAdminAreaService.findAdminAreaOfEmployee(userId);
        CommonAdminAreaDTO commonAdminAreaDTO = CommonAdminAreaProviderConverter.convertResponseDO2DTO(adminAreaOfEmployee);
        return ResponseUtils.buildSuccessResponse(commonAdminAreaDTO);
    }

    @Override
    public BaseResponse<List<CommonAdminAreaDTO>> findSubAreaList(String adminAreaCode) {
        if (Strings.isBlank(adminAreaCode)) {
            CommonAdminAreaDTO dto = new CommonAdminAreaDTO();
            dto.setValue("浙江省");
            dto.setId("33");
            dto.setLevel(1);
            return ResponseUtils.buildSuccessResponse(Lists.newArrayList(dto));
        }
        String cutdAreaCode = AdminAreaCodeUtils.getCutdAreaCode(adminAreaCode);
        List<CommonAdminAreaDO> result = commonAdminAreaService.findSubAreaList(cutdAreaCode);
        return new BaseResponse<>(true, CommonAdminAreaProviderConverter.convertListDO2Dto(result));
    }

    @Override
    public BaseResponse<List<CommonAdminAreaDTO>> findQGSubAreaList(String adminAreaCode) {
        List<CommonAdminAreaDO> result = commonAdminAreaService.findQGSubAreaList(adminAreaCode);
        return new BaseResponse<>(true, CommonAdminAreaProviderConverter.convertListDO2Dto(result));
    }

    @Override
    public BaseResponse<CommonAdminAreaDTO> getCommonAdminArea(BaseGetRequest baseGetRequest) {
        return null;
    }

    @Override
    public BaseResponse<Integer> deleteCommonAdminArea(BaseDeleteRequest deleteRequest) {
        return null;
    }

    @Override
    public String analyseAreaCodeByBasicInfo(String address) {

        log.info("地址：{}", address);
        if (Strings.isBlank(address)) {
            return null;
        }
        SoldierBasicInfoDTO dto =new SoldierBasicInfoDTO();
        dto.setResidentAddress(address);

        String areaCode = analyseAreaCodeByBasicInfo(dto).getDto();
        return areaCode;
    }

    @Override
    public BaseResponse<String> analyseAreaCodeByBasicInfoForOther(String address) {
        return null;
    }

    @Override
    public BaseResponse<String> analyseAreaCodeByBasicInfo(SoldierBasicInfoDTO dto) {

        initAreaTree();

        SoldierBasicInfoDO infoDO = new SoldierBasicInfoDO();
        BeanUtils.copyProperties(dto, infoDO);
        String areaCode = recursiveGetAreaCode(hzShiMap, infoDO);
        if (areaCode.startsWith("!")) {
            areaCode = areaCode.substring(1, areaCode.length());
        } else if (areaCode.startsWith("@")) {
            areaCode = areaCode.substring(1, areaCode.length());
        } else if (areaCode.startsWith("#")) {
            areaCode = areaCode.substring(1, areaCode.length());
        } else if (areaCode.startsWith("$")) {
            areaCode = areaCode.substring(1, areaCode.length());
        }
        return ResponseUtils.buildSuccessResponse(areaCode);
    }

    private String recursiveGetAreaCode(Map<String, AreaCodeEntity> areaMap, SoldierBasicInfoDO soldierBasicInfoDO) {
        for (String s : areaMap.keySet()) {
            if (soldierBasicInfoDO.getResidentAddress().contains(s)) {
                AreaCodeEntity areaCodeEntity = areaMap.get(s);


                if (areaCodeEntity.getFather().getNickName().contains(areaCodeEntity.getNickName())) {
                    if (soldierBasicInfoDO.getResidentAddress().contains(areaCodeEntity.getValue())) {
                        Map<String, AreaCodeEntity> childMap = areaCodeEntity.getChildMap();
                        if (!CollectionUtils.isEmpty(childMap)) {
                            return recursiveGetAreaCode(childMap, soldierBasicInfoDO);
                        } else {
                            return areaCodeEntity.getId();
                        }
                    } else {
                        continue;

                    }
                }

                Map<String, AreaCodeEntity> childMap = areaCodeEntity.getChildMap();
                if (!CollectionUtils.isEmpty(childMap)) {
                    return recursiveGetAreaCode(childMap, soldierBasicInfoDO);
                } else {
                    return areaCodeEntity.getId();
                }
            }
        }
        String collector = soldierBasicInfoDO.getCollector();
        String collectionUnit = soldierBasicInfoDO.getCollectionUnit();
        if (Strings.isNotBlank(collector)) {
            for (AreaCodeEntity areaCodeEntity : areaMap.values()) {
                if (collector.contains(areaCodeEntity.getValue())) {
                    Map<String, AreaCodeEntity> childMap = areaCodeEntity.getChildMap();
                    if (!CollectionUtils.isEmpty(childMap)) {
                        return recursiveGetAreaCode(childMap, soldierBasicInfoDO);
                    } else {
                        return "#" + areaCodeEntity.getId();
                    }
                }
            }
        }

        if (Strings.isNotBlank(collectionUnit)) {
            for (AreaCodeEntity areaCodeEntity : areaMap.values()) {
                if (collectionUnit.contains(areaCodeEntity.getValue())) {
                    Map<String, AreaCodeEntity> childMap = areaCodeEntity.getChildMap();
                    if (!CollectionUtils.isEmpty(childMap)) {
                        return recursiveGetAreaCode(childMap, soldierBasicInfoDO);
                    } else {
                        return "!" + areaCodeEntity.getId();
                    }
                }
            }
        }


        for (AreaCodeEntity value : areaMap.values()) {
            return "@" + value.getFather().getId();
        }

        return "";
    }

    private void initAreaTree() {
        if (hzShiMap == null) {
            List<AreaCodeEntity> subAreaTree = findSubAreaTree();
            Collections.sort(subAreaTree, new Comparator<AreaCodeEntity>() {
                @Override
                public int compare(AreaCodeEntity o1, AreaCodeEntity o2) {
                    if (o1.getValue().equals("西湖区")) {
                        return 1;
                    }
                    return -1;
                }
            });
            Map<String, AreaCodeEntity> shiMap = Maps.newLinkedHashMap();
            for (AreaCodeEntity areaCodeEntity : subAreaTree) {
                shiMap.put(areaCodeEntity.getNickName(), areaCodeEntity);
            }
            hzShiMap = shiMap;
        }
    }

    private List<AreaCodeEntity> findSubAreaTree() {
        List<CommonAdminAreaDO> allSubArea = commonAdminAreaService.getAllSubArea("3301%");
        Collections.sort(allSubArea, new Comparator<CommonAdminAreaDO>() {
            @Override
            public int compare(CommonAdminAreaDO o1, CommonAdminAreaDO o2) {
                return o1.getId().compareTo(o2.getId());
            }
        });


        HashMap<String, AreaCodeEntity> treeMap = Maps.newHashMapWithExpectedSize(allSubArea.size());
        int baseLevel = AdminAreaCodeUtils.getLevel("3301");
        for (CommonAdminAreaDO dictArea : allSubArea) {

            if (dictArea.getId().equals("330101000000")) {
                continue;
            }

            AreaCodeEntity bo = convertToBO(dictArea);
            treeMap.put(dictArea.getId(), bo);
            AreaCodeEntity dictAreaBO = treeMap.get(dictArea.getParentId());
            if (dictAreaBO != null) {
                bo.setFather(dictAreaBO);
                dictAreaBO.getChildMap().put(bo.getNickName(), bo);
                dictAreaBO.getChildArea().add(bo);
            }
        }

        List<AreaCodeEntity> result = Lists.newArrayList();
        for (String s : treeMap.keySet()) {
            if (AdminAreaCodeUtils.getLevel(s) == baseLevel + 1) {
                result.add(treeMap.get(s));
            }
        }

        return result;
    }

    private AreaCodeEntity convertToBO(CommonAdminAreaDO dictArea) {
        AreaCodeEntity bo = new AreaCodeEntity();
        BeanUtils.copyProperties(dictArea, bo);
        bo.setId(dictArea.getId());

        bo.setNickName(repeatValue(bo.getValue()));
        return bo;
    }

    @Override
    public void testConvertToArea() {
        commonAdminAreaService.testConvertToArea();
    }

    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    TransactionDefinition transactionDefinition;

    @Override
    public void updateCommonAllFullValuePath(String code) {
        List<CommonAdminAreaDO> allSubAreaOfQg = commonAdminAreaService.getAllSubAreaOfQg(code);
        Map<String, CommonAdminAreaDO> idMap = allSubAreaOfQg.stream().collect(Collectors.toMap(s -> s.getId(), s -> s));

        for (CommonAdminAreaDO commonAdminAreaDO : allSubAreaOfQg) {
            String fullValuePath  = recursiveGetFullPath(commonAdminAreaDO.getId(), idMap);
            commonAdminAreaDO.setFullValuePath(fullValuePath);
        }

        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try{
            for (CommonAdminAreaDO commonAdminAreaDO : allSubAreaOfQg) {
                commonAdminAreaService.updateOfQg(commonAdminAreaDO);
            }


            dataSourceTransactionManager.commit(transactionStatus);
        }catch(Exception e){

            dataSourceTransactionManager.rollback(transactionStatus);
        }
    }

    @Override
    public void testCleanSetSoldier() {

    }

    @Override
    public BaseResponse<String> convertAndSetNewResidentCode(String areaCode) {
        return null;
    }

    @Override
    public BaseResponse<String> refreshToOriginAdminAreaCode(String adminAreaCode) {
        return null;
    }

    @Override
    public BasePagingResponse<List<CommonAdminAreaDTO>> searchCommonAdminArea(CommonAdminAreaSearchRequest searchRequest) {

        final BasePagingResponse<List<CommonAdminAreaDTO>> basePagingResponse = new BasePagingResponse<>();
        serviceTemplate.execute(basePagingResponse, new ServiceCallback() {
            @Override
            public void check() {
                BizCheckUtil.checkNotNull(searchRequest, "查询分页CommonAdminArea的请求参数不能为空");
            }

            @Override
            public void executeService() {
                final CommonAdminAreaBSearcher commonAdminAreaBSearcher = CommonAdminAreaProviderConverter.convertRequestSO2Searcher(searchRequest);
                final List<CommonAdminAreaDO> commonAdminAreaDOList = commonAdminAreaService.search(commonAdminAreaBSearcher);
                final List<CommonAdminAreaDTO> commonAdminAreaDTOList = CommonAdminAreaProviderConverter.convertResponseDOList2DTOList(commonAdminAreaDOList);
                ResponseUtils.buildSuccessPagingResponse(basePagingResponse, commonAdminAreaDTOList, searchRequest, commonAdminAreaBSearcher.getTotalCount());
            }

            @Override
            public ScenarioCodeEnum getScenarioEnum() {
                return ScenarioCodeEnum.COMMON_ADMIN_AREA_SEARCH;
            }
        });

        return basePagingResponse;
    }

    private String recursiveGetFullPath(String id, Map<String, CommonAdminAreaDO> idMap) {
        if (Strings.isBlank(id)) {
            return "";
        }

        CommonAdminAreaDO commonAdminAreaDO = idMap.get(id);
        BizCheckUtil.checkNotNull(commonAdminAreaDO);

        return recursiveGetFullPath(commonAdminAreaDO.getParentId(), idMap) + "/" + commonAdminAreaDO.getValue();
    }
































    private String repeatValue(String value) {
        if (value.startsWith("米市巷")) {
            return "米市巷";
        }

        value = value.replace("市", "");
        value = value.replace("区", "");
        value = value.replace("街道", "");
        value = value.replace("社区", "");
        value = value.replace("镇", "");
        value = value.replace("村", "");
        value = value.replace("村委会", "");
        value = value.replace("委会", "");
        value = value.replace("委员会", "");
        value = value.replace("县", "");
        value = value.replace("乡", "");
        value = value.replace("社", "");
        value = value.replace("路", "");
        return value;
    }

    public static void main(String[] args) {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("330103001", "330105101");
        map.put("330103002", "330105102");
        map.put("330103003", "330105103");
        map.put("330103005", "330105105");
        map.put("330103006", "330105106");
        map.put("330103007", "330105107");
        map.put("330103008", "330105108");
        map.put("330103009", "330105109");

        map.put("330104005", "330102105");
        map.put("330104006", "330102106");
        map.put("330104007", "330102107");
        map.put("330104008", "330102108");
        map.put("330104011", "330102111");
        map.put("330104012", "330102112");
        map.put("330104013", "330102113");
        map.put("330104014", "330102114");

        map.put("330110001", "330141001");
        map.put("330110003", "330141003");
        map.put("330110002", "330141002");
        map.put("330110004", "330141004");
        map.put("330110007", "330141007");
        map.put("330110006", "330141006");
        map.put("330110008", "330141008");
        map.put("330110102", "330141102");




        String template = "update job_recruit_position  set work_city = REPLACe(work_city, '%s','%s')\n" +
                "where work_city like '%s';";
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String ori = entry.getKey();
            String oriLike =  ori + "%";
            String target = entry.getValue();
            System.out.println(String.format(template, ori, target, oriLike));
        }


        Map<String, String> twoMap = new LinkedHashMap<>();
        twoMap.put("330103000000", "330105000000");
        twoMap.put("330104000000", "330102000000");
        String t2 = "update job_recruit_position  set work_city = '%s'\n" +
                "where work_city = '%s';";
        for (Map.Entry<String, String> entry : twoMap.entrySet()) {
            String ori = entry.getKey();
            String target = entry.getValue();
            System.out.println(String.format(t2, target, ori));
        }

    }
}
